package traffic;

import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

public class Road {

    static class point {

        int x;
        int y;
        int z;

        public point(int x, int y, int z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public void add(int t) {
            if (x < y) {
                x += t;
            }
        }

        public void reduce(int t) {
            if (x > 0) {
                x -= t;
            }
        }

        public int getfree() {
            return y - x;
        }

        public int getCount() {
            return x;
        }

        public int getTime() {
            if (x > y / 2) {
                return (int) ((double) z / ((double) y / (double) x));
            } else {
                return z;
            }
        }
    }

    static class Node {

        ArrayList<Integer> nodes = new ArrayList<Integer>();
        ArrayList<point> capacity = new ArrayList<point>();

        public Node() {
        }

        public void add(int n, int x, int y, int z) {
            nodes.add(n);
            capacity.add(new point(x, y, z));
        }
    };
    private ArrayList<Node> lGraph = new ArrayList<Node>();
    private int current;
    private int remain;
    ArrayList<Integer> path;

    public Road() {
    }

    public void add() {
        lGraph.add(new Node());
    }

    public void addArc(int n, int m, int x, int y, int z) {
        lGraph.get(n).add(m, x, y, z);
    }

    public ArrayList<Integer> getPath(int n, int m) {
        path = new ArrayList<Integer>();
        path.add(n);
        int index = n;
        while (index != m) {
            int min = -1;
            for (int i = 0; i < lGraph.get(index).nodes.size(); i++) {
                if (!path.contains(lGraph.get(index).nodes.get(i))) {
                    if (min == -1) {
                        min = i;
                    } else {
                        if (lGraph.get(index).capacity.get(i).getTime() < lGraph.get(index).capacity.get(min).getTime()) {
                            min = i;
                        }
                    }
                }
            }
            index = lGraph.get(index).nodes.get(min);
            path.add(index);
        }
        return path;
    }

    public void update() {
        Random r = new Random();
        for (int i = 0; i < lGraph.size(); i++) {
            for (int j = 0; j < lGraph.get(i).capacity.size(); j++) {
                if (r.nextInt() % 2 == 0) {
                    if (lGraph.get(i).capacity.get(j).getfree() > 0) {
                        lGraph.get(i).capacity.get(j).add(r.nextInt() % (lGraph.get(i).capacity.get(j).getfree() / 2));
                    }
                } else {
                    if (lGraph.get(i).capacity.get(j).getCount() > 0) {
                        lGraph.get(i).capacity.get(j).reduce(r.nextInt() % (lGraph.get(i).capacity.get(j).getCount() / 2));
                    }
                }
            }
        }
    }

    public void move(final int d) {
        final AtomicInteger current = new AtomicInteger(path.get(0));
        int j = 0;
        while (lGraph.get(current.get()).nodes.get(j) != path.get(1)) {
            j++;
        }
        final AtomicInteger remain = new AtomicInteger(lGraph.get(current.get()).capacity.get(j).getTime());
        final Timer timer = new Timer();
        TimerTask task = new TimerTask() {

            @Override
            public void run() {
                remain.addAndGet(-10);
                if (remain.get() == 0) {
                    update();
                    getPath(path.get(1), d);
                    current.set(path.get(0));
                    int j = 0;
                    while (path.size()>1 && lGraph.get(current.get()).nodes.get(j) != path.get(1)) {
                        j++;
                    }
                    remain.set(lGraph.get(current.get()).capacity.get(j).getTime());
                    System.out.println("Current: " + current.get());
                    System.out.println("Оптимальный путь:");
                    for (int i = 0; i < path.size(); i++) {
                        System.out.print(path.get(i) + " ");
                    }
                    System.out.println("");
                    if (current.get() == d) {
                        timer.cancel();
                    }
                }
            }
        };
        timer.scheduleAtFixedRate(task, 200, 200);
    }
}